//Copyright (c) 2006-2007 Microsoft Corporation.  All rights reserved
using System;
using System.Globalization;
using System.IO;
using System.Reflection;

using InvocationFramework.Common.Library;

namespace InvocationFramework.Adapters.Inproc
{
    /// <summary>
    /// Este helper permite resolver referenciar de assemblies que no se encuentran en el directorio de 
    /// ejecucion ni en la GAC
    /// </summary>
    /// <author>Rodolfo Finochietti 16/05/2005 16.48</author>
    internal static class AssemblyResolver
    {
        #region Properties

        /// <summary>
        /// Flag para saber si ya se inicio el resolvedor
        /// </summary>
        private static bool _started;

        #endregion

        #region Properties

        /// <summary>
        /// Variable privada para el manejo de la propiedad
        /// </summary>
        private static string _assembliesFolder;

        /// <summary>
        /// Directorio donde se encuentran los assemblies que el resolvedor debe buscar
        /// </summary>
        public static string AssembliesFolder
        {
            set
            {
                _assembliesFolder = value;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Inicia el resolvedor de ubicacion de assemblies
        /// </summary>
        public static void Start( )
        {
            Start( String.Empty );
        }
        
        /// <summary>
        /// Inicia el resolvedor de ubicacion de assemblies
        /// </summary>
        /// <param name="assembliesFolder">Directorio donde se encuntran los assemblies que el resolvedor debe buscar</param>
        public static void Start( string assembliesFolder )
        {
            if ( !_started )
            {
                _assembliesFolder = assembliesFolder;

                //Me atacho al evento que me permite resolver las dependencias de los servicios (por ejemplo si lo contratos estan en assemblys separados
                AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler( currentDomain_AssemblyResolve );

                _started = true;
            }
        }

        #endregion

        #region Events

        private static Assembly currentDomain_AssemblyResolve( object sender, ResolveEventArgs args )
        {
            if ( String.IsNullOrEmpty( _assembliesFolder ) )
            {
                return null;
            }
            else
            {
                //Si falta alguna dependencia asumo que la puedo encontrar en el directorio de servicios y trato de cargar el assembly desde alli
                string[] dependency = args.Name.Split( ',' );
                string dependencyFullPath = null;

                if ( dependency.GetUpperBound( 0 ) > 0 )
                    dependencyFullPath = Path.Combine( _assembliesFolder, String.Format( CultureInfo.InvariantCulture, "{0}.dll", dependency[ 0 ] ) );

                if ( String.IsNullOrEmpty( dependencyFullPath ) && File.Exists( dependencyFullPath ) )
                    return null;
                else
                    return ReflectionHelper.GetAssembly( dependencyFullPath, null );
            }
        }
        
        #endregion
    }
}